package org.sws.domain.strategy.service.armory;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.sws.domain.strategy.enums.StrategyAlgorithm;
import org.sws.domain.strategy.model.entity.StrategyAwardEntity;
import org.sws.domain.strategy.service.armory.algorithm.IAlgorithm;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * @author joyboy
 * @description 抽奖策略、调度实现类
 */
@Slf4j
@Service
public class StrategyArmoryDispatch extends AbstractStrategyAlgorithm{

    // 抽奖策略算法
    private final Map<String, IAlgorithm> algorithmMap;
    // 抽奖算法阈值，在多少范围内开始选择不同选择。奖品概率范围长度在10000以内，使用o1复杂度算法，大于10000进行分阶梯使用oLogN算法
    private final Integer ALGORITHM_THRESHOLD_VALUE = 10000;

    public StrategyArmoryDispatch(Map<String, IAlgorithm> algorithmMap) {
        this.algorithmMap = algorithmMap;
    }

    @Override
    protected void armoryAlgorithm(String key, List<StrategyAwardEntity> strategyAwardEntities) {
        // 获取最小概率值, 去除末尾无效0
        BigDecimal minAwardRate = strategyAwardEntities.stream()
                .map(StrategyAwardEntity::getAwardRate)
                .min(BigDecimal::compareTo)
                .orElse(BigDecimal.ZERO)
                .stripTrailingZeros();

        // 用 1 * 1000 获得概率范围，百分位、千分位、万分位
        BigDecimal rateRange = convert(minAwardRate);
        if(rateRange.compareTo(BigDecimal.valueOf(ALGORITHM_THRESHOLD_VALUE)) < 0){
            algorithmMap.get(StrategyAlgorithm.O1.getKey()).armoryAlgorithm(key, strategyAwardEntities, rateRange);
            // 缓存对应的算法beanName，用于执行抽奖获取对应bean
            strategyRepository.cacheAlgorithmBeanName(key, StrategyAlgorithm.O1.getKey());
        }else {
            algorithmMap.get(StrategyAlgorithm.OLogN.getKey()).armoryAlgorithm(key, strategyAwardEntities, rateRange);
            strategyRepository.cacheAlgorithmBeanName(key, StrategyAlgorithm.OLogN.getKey());
        }


    }

    @Override
    protected Integer dispatchAlgorithm(String key) {
       String beanName = strategyRepository.getAlgorithmBeanName(key);
        IAlgorithm iAlgorithm = algorithmMap.get(beanName);
        return iAlgorithm.dispatchAlgorithm(key);
    }

}
